#include "oEditor.h"
#include "oSyntaxHighlighter.h"
#include "oNumberBar.h"
#include "oTextEdit.h"

oEditor::oEditor(QWidget* parent, const QString& filePath):
QFrame(parent),
_filePath(filePath)
{
	_view = new oTextEdit(QFont(), this);
    _view->setAcceptRichText(false);
//    _view->setTabStopDistance(fontMetrics().boundingRect(QString("0000")).width());
    _view->setLineWrapMode(QTextEdit::WidgetWidth);
    _view->setFrameStyle(QFrame::NoFrame);

    block_count = 0;
    _numberBar = new QListWidget(this);
    _numberBar->setVerticalScrollMode((QAbstractItemView::ScrollPerPixel));
    _numberBar->setFixedWidth(50);
    _numberBar->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    _numberBar->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    _numberBar->setLayoutDirection(Qt::RightToLeft);
    connect(_view, SIGNAL(blockCountChanged(int)), this, SLOT(updateLineNums(int)));
    connect(_numberBar, SIGNAL(itemClicked(QListWidgetItem *)), this, SLOT(line_number_click(QListWidgetItem *)));

//    _numberBar->setStyleSheet("padding-top: 1px;");



    QObject::connect(_view->verticalScrollBar(), &QScrollBar::valueChanged , _numberBar->verticalScrollBar(), &QScrollBar::setValue);
    QObject::connect(_numberBar->verticalScrollBar(), &QScrollBar::valueChanged ,_view->verticalScrollBar(), &QScrollBar::setValue);

    _box = new QHBoxLayout(this);
    _box->setSpacing(0);
    _box->setContentsMargins(0, 0, 0, 0);
    _box->addWidget(_numberBar);
    _box->addWidget(_view);

    QCompleter* completer = new QCompleter(this);
    completer->setModelSorting(QCompleter::CaseInsensitivelySortedModel);
    completer->setCaseSensitivity(Qt::CaseInsensitive);
    completer->setWrapAround(false);
    _view->setCompleter(completer);

    QFile file(filePath);
	file.open(QFile::ReadOnly | QFile::Text);
    QTextStream in(&file);
    _view->setPlainText(in.readAll());
    _view->document()->setModified(false);
    updateLineNums(_view->document()->blockCount());
    QObject::connect(_view->document(),SIGNAL(modificationChanged(bool)),this,SLOT(documentChanged(bool)));
    QObject::connect(_view ,SIGNAL(textChanged()), this,SLOT(update_line_number_height()));

}


void oEditor::updateLineNums(int newBlockCount){
    qDebug() << "updateLineNums:" << newBlockCount;
    if (newBlockCount > block_count){
        //  Add Line Numbers
        while (block_count < newBlockCount){
            block_count++;
            QString lineNum = QString::number(block_count);
            QListWidgetItem *item = new QListWidgetItem;
            item->setText(lineNum);
            item->setSizeHint(QSize(50, 20));
            _numberBar->addItem(item);
        }

    } else {
        //  Remove Line Numbers
        while (block_count > newBlockCount){
            _numberBar->takeItem(block_count - 1);
            block_count--;
        }
    }

    update_line_number_height();
}

void oEditor::update_line_number_height()
{
    QAbstractTextDocumentLayout* layout = _view->document()->documentLayout();

    const QFontMetrics fm = fontMetrics();
    int lineCount = 1;
    _view->update();
    for (QTextBlock block = _view->document()->begin(); block.isValid(); block = block.next(), ++lineCount)
    {
        const QRectF boundingRect = layout->blockBoundingRect(block);
        int block_height = int(boundingRect.height());
        qDebug() << "lineCount:" << lineCount << "block_height:" << block_height;
        if(block_height == 0){
            _numberBar->item(lineCount-1)->setSizeHint(QSize(50, 20));
        } else {
            _numberBar->item(lineCount-1)->setSizeHint({50, block_height});
        }

    }
}

void oEditor::line_number_click(QListWidgetItem *item)
{
    int lineno = _numberBar->row(item);

    if (!_view->isReadOnly()) {
        QList<QTextEdit::ExtraSelection> extraSelections;
        QTextEdit::ExtraSelection selection;

        QColor lineColor = QColor(240, 240, 240);
        selection.format.setBackground(lineColor);
        selection.format.setProperty(QTextFormat::FullWidthSelection, true);

        int position = _view->document()->findBlockByLineNumber(lineno).position();
        selection.cursor = _view->textCursor();
        selection.cursor.setPosition(position);
        extraSelections.append(selection);
        _view->setExtraSelections(extraSelections);
    }
}

oEditor::~oEditor()
{ }

void oEditor::setFont(const QFont& font)
{
	QFrame::setFont(font);
	_view->setFont(font);
	_numberBar->setFont(font);
}

void oEditor::documentChanged(bool modified)
{
    emit editorChanged(this, modified);
}

QString oEditor::getFileName()
{
    return QFileInfo(_filePath).fileName();
}

const QString& oEditor::getFilePath()
{
    return _filePath;
}

bool oEditor::isModified()
{
    return _view->document()->isModified();
}

void oEditor::save()
{
    if (_view->document()->isModified())
    {
        QFile file(_filePath);
        if (file.open(QFile::WriteOnly | QFile::Truncate))
        {
            QTextStream out(&file);
            out << _view->toPlainText();
            _view->document()->setModified(false);
        }
    }
}

oTextEdit* oEditor::view()
{
    return _view;
}
